import 'package:flutter/material.dart';
import 'package:mybase/base/animate_do/types/animate_do_mixins.dart';
import 'package:mybase/base/animate_do/types/animate_do_types.dart';
import 'package:mybase/base/tool/globalMethod/FFScript.dart';

typedef FFAnimate2Builder = Widget Function(
  AnimationController controller,
  double progress,
);

//注意 key值一定要赋
class FFAnimate2 extends StatefulWidget {
  // 自动开始
  bool autoStart;

  // 是否无限循环 （循环:从begin到end）
  bool repeat;

  // 是否无限循环 （循环:从begin到end，再从end到begin）
  bool repeat2;

  // 当repeat2，到end时，停留多久
  Duration? toEndDelay;

  // 当repeat2，到start时，停留多久
  Duration? toStartDelay;

  // 构建器
  FFAnimate2Builder builder;

  // 是否手动触发
  bool manualTrigger;

  // 控制器
  Function(AnimationController controller)? controller;

  // 时长
  Duration duration;

  // 延迟
  Duration delay;

  // true:正向执行一次 false:反向执行一次
  bool animate;

  // 开始值
  double begin;

  // 结束值
  double end;

  // 曲线
  // Curves.easeIn: 逐渐加速
  // Curves.easeOut: 逐渐减速
  final Curve curve;

  // 动画结束回调
  Function(AnimationController controller, AnimateDoDirection direction)? onFinish;

  // 动画到达结束回调
  Function(AnimationController controller)? onToEnd;

  // 动画回到起点回调
  Function(AnimationController controller)? onToBegin;

  FFAnimate2({
    Key? key,
    this.autoStart = true,
    this.repeat = false,
    this.repeat2 = false,
    this.toEndDelay,
    this.toStartDelay,
    this.duration = const Duration(milliseconds: 1000),
    this.delay = const Duration(milliseconds: 0),
    this.controller,
    this.manualTrigger = false,
    this.animate = true,
    this.begin = 0,
    this.end = 1,
    this.onFinish,
    this.onToEnd,
    this.onToBegin,
    this.curve = Curves.linear,
    required this.builder,
  }) : super(key: key) {
    // if (manualTrigger == true && controller == null) {
    //   throw FlutterError('如果你想使用 manualTrigger:true， \n\n'
    //       '你必须实现回调 Function(AnimationController controller)? controller. \n\n');
    // }

    if (repeat2 && repeat) {
      throw FlutterError('repeat2 和 repeat 不能同时设置为true， \n\n');
    }
  }

  @override
  State<FFAnimate2> createState() => _FFAnimate2State();
}

class _FFAnimate2State extends State<FFAnimate2> with SingleTickerProviderStateMixin, AnimateDoState {
  late Animation<double> animation;

  @override
  void dispose() {
    disposed = true;
    controller.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();

    controller = AnimationController(duration: widget.duration, vsync: this);
    animation = Tween<double>(begin: widget.begin, end: widget.end)
        .animate(CurvedAnimation(parent: controller, curve: widget.curve));

    configAnimation(
      autoStart: widget.autoStart,
      delay: widget.delay,
      animate: widget.animate,
      manualTrigger: widget.manualTrigger,
      infinite: widget.repeat,
      onFinish: widget.onFinish != null
          ? (AnimateDoDirection p) {
              widget.onFinish?.call(controller, p);
            }
          : null,
      controllerCallback: widget.controller,
      onToEnd: (c) async {
        if (widget.repeat2) {
          if (widget.toEndDelay != null) {
            await Future.delayed(widget.toEndDelay!);
            if (!mounted) return;
            c.reverse();
          } else {
            c.reverse();
          }
        }
        widget.onToEnd?.call(c);
      },
      onToBegin: (c) async {
        if (widget.repeat2) {
          if (widget.toStartDelay != null) {
            await Future.delayed(widget.toStartDelay!);
            if (!mounted) return;
            c.forward();
          } else {
            c.forward();
          }
        }
        widget.onToBegin?.call(c);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    buildAnimation(
      autoStart: widget.autoStart,
      delay: widget.delay,
      animate: widget.animate,
      manualTrigger: widget.manualTrigger,
      infinite: widget.repeat,
      onFinish: widget.onFinish != null
          ? (AnimateDoDirection p) {
              widget.onFinish?.call(controller, p);
            }
          : null,
      controllerCallback: widget.controller,
    );

    return AnimatedBuilder(
      animation: controller,
      builder: (BuildContext context, Widget? child) {
        return widget.builder(controller, animation.value);
      },
    );
  }
}
